package com.ljm.commom.web.http;

import com.ljm.commom.web.utils.SqlFilterUtil;
import org.apache.commons.io.IOUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 多次读取请求体处理
 * @author edu
 */
public class BodyReaderRequestWrapper extends HttpServletRequestWrapper {
    private static final Logger logger= LoggerFactory.getLogger(BodyReaderRequestWrapper.class);
    private byte[] body = new byte[0];
    /**
     * @param request 请求
     */
    public BodyReaderRequestWrapper(HttpServletRequest request) {
        super(request);
        try {
            ServletInputStream inputStream=request.getInputStream();
            if(null!=inputStream&&request.getContentLength()>0){
                body=getRequestBody(inputStream);
            }
        } catch (IOException e) {
            logger.error("BodyReaderRequestWrapper read inputStream error={} ",e);
        }
    }

    private byte[] getRequestBody(InputStream inputStream){
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        try {
            IOUtils.copy(inputStream,byteArrayOutputStream);
            body=byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            logger.error("BodyReaderRequestWrapper get request body error",e);
        }finally {
            try {
                byteArrayOutputStream.close();
            } catch (IOException e) {
                logger.error("BodyReaderRequestWrapper get request body,close inputStream error",e);
            }
        }
        return body;
    }

    /**
     * 覆盖getParameter方法，将参数名和参数值都做xss过滤。
     * 如果需要获得原始的值，则通过super.getParameterValues(name)来获取
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value != null) {
            value = Jsoup.clean(value,Whitelist.relaxed()).trim();
            //处理sql注入
            SqlFilterUtil.sqlInject(value);
        }
        return value;
    }

    /**
     * 重写处理xss攻击
     * @param name 参数名称
     * @return 请求参数
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values != null) {
            int length = values.length;
            String[] escapseValues = new String[length];
            for (int i = 0; i < length; i++) {
                // 防xss攻击和过滤前后空格
                escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim();
                //处理sql注入
                SqlFilterUtil.sqlInject(escapseValues[i]);
            }
            return escapseValues;
        }
        return super.getParameterValues(name);
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map = new LinkedHashMap<>();
        Map<String, String[]> parameters = super.getParameterMap();
        for (String key : parameters.keySet()) {
            String[] values = parameters.get(key);
            for (int i = 0; i < values.length; i++) {
                // 防xss攻击和过滤前后空格
                values[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim();
            }
            map.put(key, values);
        }
        return map;
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read(){
                return byteArrayInputStream.read();
            }
        };
    }
}
